using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Web;
using System.IO;

namespace Web.Ajax.Configuration
{
    public class Logs : ConfigurationSection
    {     
             

        [ConfigurationProperty("endpoints", DefaultValue = null)]
        public LogEndpoints Endpoints
        {
            get
            {

                return (LogEndpoints)this["endpoints"];   
            }
            set
            {
                this["endpoints"] = value;
            }
        }
        

        private static Logs current;
        public static Logs Current
        {
            get
            {
                if (current == null)
                {
                    try
                    {
                        object o = ConfigurationManager.GetSection("Logs");
                        if (o is Logs)
                            current = (Logs)o;
                        else
                            current = new Logs();
                    }
                    catch (Exception)
                    {
                        current = new Logs();
                    }
                }
                return current; 
            }
        }

        private static LogEndpoint DefaultEndpoint;
        public LogEndpoint GetEndpoint()
        {
            LogEndpoints list = this.Endpoints;
            string RequestUrl=null;

            if (HttpContext.Current != null&&HttpContext.Current.ApplicationInstance!=null)
            {
                RequestUrl = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath;
            }
            if (list != null && list.Count > 0)
            {
                foreach (LogEndpoint e in list)
                {
                    if (e.Key == "Default" && DefaultEndpoint==null)
                        DefaultEndpoint = e;
                    if (e.Url != null && RequestUrl != null)
                    {
                        if (e.Url.ToLower() == RequestUrl.ToLower())
                            return e;
                    }
                }
            }
            if (DefaultEndpoint == null)
                DefaultEndpoint = new LogEndpoint();
            return DefaultEndpoint;
        }        
    }

    public class LogEndpoints : ConfigurationElementCollection
    {
        public LogEndpoints()
        {
            this.AddElementName = "endpoint";
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new LogEndpoint();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            string key=((LogEndpoint)element).Key;
            if (key == null)
            {
                throw new Exception("Logging configuration error. LogEndpoint must have a key attribute.");
            }
            return key;
        }
    }

    public class LogEndpoint : ConfigurationElement
    {       
        [ConfigurationProperty("Key", DefaultValue = null)]
        public string Key
        {
            get
            {
                return (String)this["Key"];
            }
            set
            {
                this["Key"] = value;
            }
        }

        private string folder;
        [ConfigurationProperty("Folder", DefaultValue = "c:\\Logs\\")]
        public string Folder
        {
            get
            {
				if (folder == null || Roll == Logging.Roll.Request)
                {
                    folder = (String)this["Folder"];
                    if (AppFolder)
                    {
						string AppPath;
						if (HttpContext.Current != null && HttpContext.Current.Request != null)
							AppPath = HttpContext.Current.Request.PhysicalApplicationPath;
						else
							AppPath=AppDomain.CurrentDomain.BaseDirectory;

						if (!string.IsNullOrEmpty(AppPath))
						{
							string[] parts = AppPath.Split('\\');
							if (parts.Length > 2)
								folder += parts[parts.Length - 2] + "\\";
						}

                    }
                    if (Roll == Logging.Roll.Request)
                        folder += DateTime.Now.ToString("yyyy.MM.dd") + "\\";
                    try
                    {
                        if (!Directory.Exists(folder))
                            Directory.CreateDirectory(folder);
                    }
                    catch { }
                }
                return folder;
            }
            set
            {
                this["Folder"] = value;
                folder = null;
            }
        }        

        [ConfigurationProperty("Roll", DefaultValue = "Daily")]
        private string roll
        {
            get
            {

                return (string)this["Roll"];
            }
            set
            {
                this["Roll"] = value;
            }
        }
        public Web.Ajax.Logging.Roll Roll
        {
            get
            {
                return (Web.Ajax.Logging.Roll)Enum.Parse(typeof(Web.Ajax.Logging.Roll), roll);
            }
        }

        [ConfigurationProperty("Level", DefaultValue = "Debug")]
        private string level
        {
            get
            {
                return (string)this["Level"];
            }
            set
            {
                this["Level"] = value;
            }
        }
        public Web.Ajax.Logging.Level Level
        {
            get
            {
                return (Web.Ajax.Logging.Level)Enum.Parse(typeof(Web.Ajax.Logging.Level), level);
            }
        }

        [ConfigurationProperty("AppFolder", DefaultValue = true)]
        private bool AppFolder
        {
            get
            {
                return (bool)this["AppFolder"];
            }
            set
            {
                this["AppFolder"] = value;
            }
        }

        [ConfigurationProperty("Url", DefaultValue = null)]
        public string Url
        {
            get
            {
                return (string)this["Url"];
            }
            set
            {
                this["Url"] = value;
            }
        }

        public static string LogFileExtension
        {
            get
            {
                return ".json.log";
            }
        }

        public string LogFileName
        {
            get
            {
                string f="";
                switch (Roll)
                {
                    case Logging.Roll.Daily:
                        f = DateTime.Now.ToString("yyyy.MM.dd");
                        break;
                    case Logging.Roll.Request:                        
                        f = CurrentRequestFileName;
                        break;
                }                
                return f+LogFileExtension;
            }
        }

        public string LogFilePath
        {
            get
            {
                return  Folder + LogFileName;
            }
        }

        public string CurrentRequestId
        {
            get
            {
                string RequestId=null;
                if (HttpContext.Current != null)
                {
                    RequestId = (string)HttpContext.Current.Items["RequestId"];
                    if (string.IsNullOrEmpty(RequestId))
                    {
                        RequestId = Guid.NewGuid().ToString();
                        HttpContext.Current.Items["RequestId"] = RequestId;
                    }
                }
                return RequestId;
            }
        }

        private string CurrentRequestFileName
        {
            get
            {
                string file = null;
                if (HttpContext.Current != null)
                {
                    file = (string)HttpContext.Current.Items[CurrentRequestId];
                    if (string.IsNullOrEmpty(file))
                    {
                        file = DateTime.Now.ToString("HH.mm.sss") + "." + CurrentRequestId;
                        HttpContext.Current.Items[CurrentRequestId] = file;
                    }
                }
                return file;
            }
        }
    }
}
